{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# AutoEncoder\n",
    "---\n",
    "自动编码器的主要应用有两个方面，第一是**数据去噪**，第二是进行**可视化降维**。自动编码器还有一个功能，即**生成数据**。\n",
    "\n",
    "编码器和解码器可以是任意模型，通常使用神经网络模型作为编码器和解码器。\n",
    "\n",
    "输入的数据经过神经网络降维到一个编码(code)，接着通过另外一个网络剧解码得到一个和输入原数据一模一样的生成数据，然后通过比较这两个数据，最小化它们之间的差异来训练这个网络中编码器和解码器的参数。\n",
    "\n",
    "当这个过程训练完后，拿出这个解码器，随机传入一个编码(code)，通过解码器能够生成一个和原数据差不多的数据，"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "from torch.autograd import Variable\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "cudAvl = lambda x : x.cuda() if torch.cuda.is_available() else x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class autoencoder(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.encoder = nn.Sequential(\n",
    "            nn.Linear(28*28, 128),\n",
    "            nn.ReLU(True),\n",
    "            nn.Linear(128, 64),\n",
    "            nn.ReLU(True),\n",
    "            nn.Linear(64, 12),\n",
    "            nn.ReLU(True),\n",
    "            nn.Linear(12, 3)\n",
    "        )\n",
    "        \n",
    "        self.decoder = nn.Sequential(\n",
    "            nn.Linear(3, 12),\n",
    "            nn.ReLU(True),\n",
    "            nn.Linear(12, 64),\n",
    "            nn.ReLU(True),\n",
    "            nn.Linear(64, 128),\n",
    "            nn.ReLU(True),\n",
    "            nn.Linear(128, 28*28),\n",
    "            nn.Tanh()\n",
    "        )\n",
    "    \n",
    "    def forward(self, x):\n",
    "        code = self.encoder(x)\n",
    "        imgTensor = self.decoder(code)\n",
    "        return code, imgTensor\n",
    "    \n",
    "    def encode(self, x):\n",
    "        return self.encoder(x)\n",
    "    \n",
    "    def decode(self, x):\n",
    "        return self.decoder(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "net = autoencoder()\n",
    "net = cudAvl(net)\n",
    "criterion = nn.MSELoss()\n",
    "optimizer = torch.optim.Adam(net.parameters(), lr=1e-3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "42000 784\n"
     ]
    }
   ],
   "source": [
    "import csv\n",
    "\n",
    "with open('train.csv') as f :\n",
    "    lines = csv.reader(f)\n",
    "    label, attr = [], []\n",
    "    for line in lines :\n",
    "        if lines.line_num == 1 :\n",
    "            continue\n",
    "        label.append(int(line[0]))\n",
    "        attr.append([float(j) for j in line[1:]])\n",
    "print(len(label), len(attr[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([42000, 784])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "digTensor = torch.FloatTensor(attr)\n",
    "digTensor = digTensor / 255.0\n",
    "digTensor.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch [100/1500]: 0.058348119258880615\n",
      "epoch [200/1500]: 0.047589220106601715\n",
      "epoch [300/1500]: 0.042967937886714935\n",
      "epoch [400/1500]: 0.040192779153585434\n",
      "epoch [500/1500]: 0.038630422204732895\n",
      "epoch [600/1500]: 0.03767261654138565\n",
      "epoch [700/1500]: 0.037026435136795044\n",
      "epoch [800/1500]: 0.036425597965717316\n",
      "epoch [900/1500]: 0.03603523224592209\n",
      "epoch [1000/1500]: 0.0356963612139225\n",
      "epoch [1100/1500]: 0.035425879061222076\n",
      "epoch [1200/1500]: 0.035187773406505585\n",
      "epoch [1300/1500]: 0.034891996532678604\n",
      "epoch [1400/1500]: 0.03473861888051033\n",
      "epoch [1500/1500]: 0.034577593207359314\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f817eef2ac8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "epoch = 1500\n",
    "pltX, pltY = [], []\n",
    "for e in range(epoch):\n",
    "    pltX.append(e)\n",
    "    Input = cudAvl(Variable(digTensor))\n",
    "    Target = cudAvl(Variable(digTensor))\n",
    "    _, Output = net(Input)\n",
    "    loss = criterion(Output,Target)\n",
    "    print_loss = loss.data[0]\n",
    "    pltY.append(print_loss)\n",
    "    optimizer.zero_grad()\n",
    "    loss.backward()\n",
    "    optimizer.step()\n",
    "    if (e + 1) % 100 == 0:\n",
    "        print('epoch [%s/%s]: %s' %(e + 1, epoch, print_loss))\n",
    "\n",
    "plt.title('loss function output curve')\n",
    "plt.plot(pltX, pltY)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from PIL import  Image\n",
    "import numpy as np\n",
    "\n",
    "def getImage(matrix):\n",
    "    dig = np.array(matrix.numpy()).reshape((28, 28))\n",
    "    digImg = Image.fromarray(dig * 255)\n",
    "    digImg = digImg.convert('L')\n",
    "    return digImg\n",
    "\n",
    "def compare(matrix, testNet):\n",
    "    before = getImage(matrix)\n",
    "    plt.subplot(121)\n",
    "    plt.title('before encoding')\n",
    "    plt.imshow(before)\n",
    "    \n",
    "    matrix = matrix.unsqueeze(0)\n",
    "    In = cudAvl(Variable(matrix))\n",
    "    code, Out = testNet(In)\n",
    "    if torch.cuda.is_available():\n",
    "        Out = Out.cpu()\n",
    "    after = getImage(Out.data)\n",
    "    \n",
    "    plt.subplot(122)\n",
    "    plt.title('after encoding')\n",
    "    plt.imshow(after)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "image index = 36717 , number =  3 \n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nb9eiAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f81713b51d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import random\n",
    "index = random.randint(0, digTensor.shape[0])\n",
    "print('image index =', index, ', number = ', label[index], '\\n')\n",
    "\n",
    "net.eval()\n",
    "compare(digTensor[index], net)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "效果还不错~\n",
    "\n",
    "---\n",
    "\n",
    "接下来试一下以**卷积神经网络**为基础的自动编码器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class CNNautoencoder(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.encoder = nn.Sequential(\n",
    "            nn.Conv2d(1, 16, 3, stride=3, padding=1),\n",
    "            nn.ReLU(True),\n",
    "            nn.MaxPool2d(2, stride=2),\n",
    "            nn.Conv2d(16, 8, 3, stride=2, padding=1),\n",
    "            nn.ReLU(True),\n",
    "            nn.MaxPool2d(2, stride=1)\n",
    "        )\n",
    "        \n",
    "        self.decoder = nn.Sequential(\n",
    "            nn.ConvTranspose2d(8, 16, 3, stride=2),\n",
    "            nn.ReLU(True),\n",
    "            nn.ConvTranspose2d(16, 8, 5, stride=3, padding=1),\n",
    "            nn.ReLU(True),\n",
    "            nn.ConvTranspose2d(8, 1, 2, stride=2, padding=1),\n",
    "            nn.Tanh()\n",
    "        )\n",
    "    \n",
    "    def forward(self, x):\n",
    "        code = self.encoder(x)\n",
    "        transImg = self.decoder(code)\n",
    "        return code, transImg"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "CNNnet = CNNautoencoder()\n",
    "CNNnet = cudAvl(CNNnet)\n",
    "CNNcriterion = nn.MSELoss()\n",
    "CNNoptimizer = torch.optim.Adam(CNNnet.parameters(), lr=1e-3, weight_decay=1e-5)\n",
    "\n",
    "CNNdigTensor = digTensor.view(digTensor.shape[0], 1, 28, 28)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch [100/1000]: 0.06539251655340195\n",
      "epoch [200/1000]: 0.05366114154458046\n",
      "epoch [300/1000]: 0.04686489701271057\n",
      "epoch [400/1000]: 0.042550913989543915\n",
      "epoch [500/1000]: 0.0394083596765995\n",
      "epoch [600/1000]: 0.03722544014453888\n",
      "epoch [700/1000]: 0.03553758189082146\n",
      "epoch [800/1000]: 0.034192875027656555\n",
      "epoch [900/1000]: 0.03310518339276314\n",
      "epoch [1000/1000]: 0.03222407400608063\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nfRGROPL/AeLR50AV3uSMAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f81714c67f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "epoch = 1000\n",
    "pltX, pltY = [], []\n",
    "for e in range(epoch):\n",
    "    pltX.append(e)\n",
    "    Input = cudAvl(Variable(CNNdigTensor))\n",
    "    Target = cudAvl(Variable(CNNdigTensor))\n",
    "    _, Output = CNNnet(Input)\n",
    "    loss = CNNcriterion(Output,Target)\n",
    "    print_loss = loss.data[0]\n",
    "    pltY.append(print_loss)\n",
    "    CNNoptimizer.zero_grad()\n",
    "    loss.backward()\n",
    "    CNNoptimizer.step()\n",
    "    if (e + 1) % 100 == 0:\n",
    "        print('epoch [%s/%s]: %s' %(e + 1, epoch, print_loss))\n",
    "\n",
    "plt.title('loss function output curve')\n",
    "plt.plot(pltX, pltY)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f817149e5c0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "CNNnet.eval()\n",
    "compare(CNNdigTensor[index], CNNnet)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
